package com.bee.bootstrap.user.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bee.bootstrap.plugs.shiro.ShiroMd5Util;
import com.bee.bootstrap.role.entity.Role;
import com.bee.bootstrap.role.service.IRoleService;
import com.bee.bootstrap.system.entity.Area;
import com.bee.bootstrap.system.service.IAreaService;
import com.bee.bootstrap.system.service.ISmsVerifyService;
import com.bee.bootstrap.user.entity.User;
import com.bee.bootstrap.user.mapper.UserMapper;
import com.bee.bootstrap.user.service.IUserService;
import com.bee.bootstrap.userRole.entity.UserRole;
import com.bee.bootstrap.userRole.service.IUserRoleService;
import com.bee.common.core.constant.Constant;
import com.bee.common.core.enums.StatusEnum;
import com.bee.common.core.result.Result;
import com.bee.common.core.result.ResultCode;
import com.bee.common.tools.jwt.JwtUtils;
import org.apache.commons.lang.StringUtils;
import org.jose4j.lang.JoseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author liekkas
 * @since 2018-04-09
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private IAreaService areaServiceImpl;
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private ISmsVerifyService smsVerifyServiceImpl;
    @Autowired
    private IRoleService roleServiceImpl;
    @Autowired
    private IUserRoleService userRoleServiceImpl;

    @Override
    public User findUserByToken(String token) {
       User condition=new User();
       condition.setToken(token);
       condition.setStatus(StatusEnum.NORMAL.toString());
       return this.selectOne(new EntityWrapper<>(condition));
    }

    @Override
    public User findUserByUserName(String userName) {
        User condition=new User();
        condition.setUserName(userName);
        return this.selectOne(new EntityWrapper<>(condition));
    }

    @Override
    public List<User> findUsersByRoleId(Long roleId) {
        List<User> users=new ArrayList<>();
        List<UserRole> userRoles=userRoleServiceImpl.findByRoleId(roleId);
        List<Long> userIds=new ArrayList<>();
        if(userRoles!=null&&userRoles.size()>0){
            userRoles.forEach(userRole -> {
                userIds.add(userRole.getUserId());
            });
            users=this.selectList(new EntityWrapper<User>().in("id",userIds).eq("status",StatusEnum.NORMAL.toString()));
        }
        return users;
    }


    @Override
    public Result findPageView(Page<User> page, User condition) {
        EntityWrapper<User> entityWrapper = new EntityWrapper(condition);
        if(StringUtils.isNotBlank(condition.getNameQuery())){
            entityWrapper.like("name",condition.getNameQuery());
        }
        Role roleCondition=new Role();
        roleCondition.setStatus(StatusEnum.NORMAL.toString());
        List<Role> roles=roleServiceImpl.selectList(new EntityWrapper<Role>(roleCondition));
        page=this.selectPage(page,entityWrapper);
        if(page!=null&&page.getRecords()!=null){
            List<User> userList=page.getRecords();
            userList.forEach(user -> {
                user.setAreaView(StringUtils.defaultIfEmpty(user.getProvince(),"")+
                               StringUtils.defaultIfEmpty(user.getCity(),"")+
                               StringUtils.defaultIfEmpty(user.getDistrict(),""));
                user.setRoles(roles);
                user.setUserRoles(userRoleServiceImpl.findRolesCodes(user.getId()));
            });
        }
        return Result.success(page);
    }

    @Override
    public Result login(String userName, String passWord) {
        User condition=new User();
        condition.setUserName(userName);
        User persistence=this.selectOne(new EntityWrapper<>(condition));
        if(persistence==null)
            return Result.fail("用户不存在");
        if(!StatusEnum.NORMAL.toString().equals(persistence.getStatus())){
            return Result.fail("用户已失效");
        }
        String checkPassword= ShiroMd5Util.generatePassword(userName,passWord,persistence.getSalt());
        if(!persistence.getPassWord().equals(checkPassword)){
            return Result.fail("密码不正确");
        }
        return Result.success("登录成功",persistence.getToken());
    }

    @Override
    public Result updateLocation(String token, String province, String city, String code) {
        User persistence=this.findUserByToken(token);
        //修改区域信息
        if(StringUtils.isNotBlank(code)){
            Area area=areaServiceImpl.findByCode(code);
            if(area!=null){
                persistence.setCityCode(area.getCode());
                //获取省
                if(area.getParentId()!=null){
                    Area provinceArea=areaServiceImpl.selectOne(new EntityWrapper<Area>().eq("parent_id",area.getParentId()));
                    if(provinceArea!=null){
                        persistence.setProvinceCode(provinceArea.getCode());
                    }
                }
            }
        }
        persistence.setProvince(province);
        persistence.setCity(city);
        persistence.setUpdateTime(new Date());
        this.updateById(persistence);
        return Result.success("定位成功");
    }

    @Override
    public Result saveAppToken(String phone, String code) throws JoseException {
        //验证码验证
        Result result=smsVerifyServiceImpl.validCode(phone,code);
        if(ResultCode.FAIL.getCode()==(result.getCode()))
            return result;
        //查找是否已经创建了token
        User user=findUserByPhone(phone);
        if(user!=null&&StringUtils.isNotBlank(user.getToken())&&!StatusEnum.INVALID.toString().equals(user.getToken()))
            return Result.success("获取token成功",user);
        //生成token
        Map<String,Object> payLoadMap=new HashMap<String,Object>();
        payLoadMap.put("phone",phone);
        String token=jwtUtils.generateToken(Constant.JWT_ISSUER,phone,Float.valueOf(120000000), payLoadMap);
        //生成User,保存token
        if(user==null){
            user=new User();
            user.setStatus(StatusEnum.NORMAL.toString());
            user.setAccountPhone(phone);
            user.setCreateTime(new Date());
            user.setToken(token);
            insert(user);
        }else{
            user.setToken(token);
            updateById(user);
        }
        //返回结果
        return Result.success("获取token成功", user);
    }

    @Override
    public Result updateAppToken(String token, String phone, String code) throws JoseException {
        //验证码验证
        Result result=smsVerifyServiceImpl.validCode(phone,code);
        if(ResultCode.FAIL.getCode()==(result.getCode()))
            return result;
        //更改的手机号码已存在用户
        User exists=findUserByPhone(phone);
        if(exists!=null)
            return Result.fail("该手机号码已被使用");
        User condition=new User();
        condition.setStatus(StatusEnum.NORMAL.toString());
        condition.setToken(token);
        User persistence=selectOne(new EntityWrapper<>(condition));
        if(persistence==null)
            return Result.fail("token已过期");
        //找到了旧用户重新生成手机号码和token
        persistence.setAccountPhone(phone);
        //生成token
        Map<String,Object> payLoadMap=new HashMap<String,Object>();
        payLoadMap.put("phone",phone);
        String newToken=jwtUtils.generateToken(Constant.JWT_ISSUER,phone,Float.valueOf(120000000), payLoadMap);
        persistence.setToken(newToken);
        persistence.setUpdateTime(new Date());
        updateById(persistence);
        //返回结果
        return Result.success("更换手机号码成功",newToken);
    }

    @Override
    public Result deleteAppToken(String token) {
        User condition=new User();
        condition.setStatus(StatusEnum.NORMAL.toString());
        condition.setToken(token);
        User persistence=selectOne(new EntityWrapper<>(condition));
        if(persistence==null)
            return Result.fail("token已过期");
        persistence.setToken(StatusEnum.INVALID.toString());
        updateById(persistence);
        //返回结果
        return Result.success("退出登录成功");
    }

    @Override
    public Result deleteUserById(long id) {
        User user=this.selectById(id);
        user.setStatus(StatusEnum.INVALID.toString());
        this.updateById(user);
        return Result.success("删除成功");
    }

    @Override
    public Result updateUser(User user) {
        if(!this.persistenceAble(user)){
            return Result.fail("该手机号码已被使用");
        }
        if(user.getUserRoles()!=null&&user.getUserRoles().size()>0){
            userRoleServiceImpl.deleteAllUserRole(user.getId());//删除旧角色记录
            userRoleServiceImpl.addUserRole(user.getUserRoles(),user.getId());
        }
        user.setUpdateTime(new Date());
        this.updateById(user);
        return Result.success("更新成功");
    }

    @Override
    public Result addUser(User user) throws JoseException {
        if(!this.persistenceAble(user)){
            return Result.fail("该手机号码已被使用");
        }
        //生成密码盐
        String salt=UUID.randomUUID().toString().replace("-","");
        String password=ShiroMd5Util.generatePassword(user.getUserName(),user.getPassWord(),salt);
        user.setPassWord(password);
        user.setSalt(salt);
        user.setStatus(StatusEnum.NORMAL.toString());
        user.setCreateTime(new Date());
        //生成token
        Map<String,Object> payLoadMap=new HashMap<String,Object>();
        payLoadMap.put("phone",user.getAccountPhone());
        String token=jwtUtils.generateToken(Constant.JWT_ISSUER,user.getAccountPhone(),Float.valueOf(120000000), payLoadMap);
        user.setToken(token);
        this.insert(user);
        return Result.success("更新成功");
    }

    @Override
    public List<User> findUsersByIds(Set<Long> userIds) {
        return this.selectList(new EntityWrapper<User>().in("id",userIds));
    }

    @Override
    public List<User> findUsersLikeName(String userName) {
        return this.selectList(new EntityWrapper<User>().like("name",userName).eq("status",StatusEnum.NORMAL.toString()));
    }


    @Override
    public User findUserByPhone(String phone) {
        User condition=new User();
        condition.setAccountPhone(phone);
        condition.setStatus(StatusEnum.NORMAL.toString());
        return this.selectOne(new EntityWrapper<>(condition));
    }


    private boolean persistenceAble(User user){
        User persistence=this.selectOne(new EntityWrapper<User>()
                .eq("account_phone",user.getAccountPhone()).eq("status",StatusEnum.NORMAL.toString()));
        return persistence==null||(user.getId()!=null&&user.getId().compareTo(persistence.getId())==0);
    }
}
